#!/usr/bin/env python
# -*- coding:utf-8 -*-

import os, sys, signal
import asyncore, asynchat, socket, threading, time

HOST = "127.0.0.1"
PORT = 54344

def DEBUG(format, *args) : print format % args

will_stop = False

def signal_stop( signo, frame ) :
    global  will_stop
    DEBUG( "SERVER catch #%d signal, would stop.", signo )
    will_stop = True
    return
    # signal_stop

class EchoChannel(asynchat.async_chat) :
    def    __init__(self, connect, address) :
        asynchat.async_chat.__init__(self, conn=connect)
        self.__connect = connect
        self.__address = address
        self.__buf_incoming = []
        self.__terminator = '\n'
        self.set_terminator(self.__terminator)
        
    def    collect_incoming_data(self, data) :
        DEBUG('SERVER collect: >>>%s<<<', data)
        self.__buf_incoming.append(data)
    
    def    found_terminator(self) :
        DEBUG('SERVER found: >>>%s<<<', self.__buf_incoming)
        line = ''.join(self.__buf_incoming)
        self.handle(line)
        self.__buf_incoming = []
        # found_terminator()
            
    def    handle_close(self) :
        DEBUG('SERVER close connection for client "%s".', self.__address)
        self.close()
        # handle_close()
        
    def    handle(self, record) :
        DEBUG('SERVER echo: %s', record)
        self.push(record + '\n')
        
    # class EchoChannel
            
class EchoServer(asyncore.dispatcher):

    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(("", port))
        self.listen(5)
        DEBUG('SERVER listening on PORT:%d ...', port)

    def __init__2(self, port) :
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.__port = port
        sock.bind(("", port))
        DEBUG('SERVER listening on PORT:%d ...', port)
        sock.listen(1)
        
        # base class ctor
        asyncore.dispatcher.__init__(self, sock=sock)
        # this is a listening socket, will not handle_read event
        self.accepting = True
        # __init__()
        
    def handle_accept(self) :
        connect, client = self.accept()
        DEBUG('SERVER accept client %s', client)
       
        EchoChannel(connect, client)
        # handle_accept()
        
    # class EchoServer
            
def main():
    # mask signal
    signal.signal( signal.SIGTERM, signal_stop )
    if 'posix' == os.name :
        signal.signal( signal.SIGQUIT, signal_stop )

    s = EchoServer(PORT)
    try :
        asyncore.loop()
    except :
        DEBUG( "SERVER interrupt : %s", `sys.exc_info()[1]` )

if __name__ == '__main__' :
    main()
    sys.exit(0)
